<!DOCTYPE html>
<html lang="en">
  <head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, viewport-fit=cover"/>
 
<link rel="stylesheet" href="../assets/css/style.css"/> 
<!-- Copyright 1998-2021 by Northwoods Software Corporation. -->    <title> GoJS Sizing of GraphObjects -- Northwoods Software </title>
    <link rel="stylesheet" href="../assets/css/prism.css"  />
  </head>
  <script>
    
    window.diagrams = [];
    window.goCode = function(pre, w, h, parentid, animation) {
      window.diagrams.push([pre, w, h, parentid, animation]);
    }
  </script>
  <body>
  <nav id="navTop" class="w-full z-30 top-0 text-white bg-nwoods-primary">
    <div class="w-full container max-w-screen-lg mx-auto flex flex-wrap sm:flex-nowrap items-center justify-between mt-0 py-2">
      <div class="md:pl-4">
        <a class="text-white hover:text-white no-underline hover:no-underline
        font-bold text-2xl lg:text-4xl rounded-lg hover:bg-nwoods-secondary " href="../">
          <h1 class="mb-0 p-1 ">GoJS</h1>
        </a>
      </div>
      <button id="topnavButton" class="rounded-lg sm:hidden focus:outline-none focus:ring" aria-label="Navigation">
        <svg fill="currentColor" viewBox="0 0 20 20" class="w-6 h-6">
          <path id="topnavOpen" fill-rule="evenodd" d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 10a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM9 15a1 1 0 011-1h6a1 1 0 110 2h-6a1 1 0 01-1-1z" clip-rule="evenodd"></path>
          <path id="topnavClosed" class="hidden" fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path>
        </svg>
      </button>
      <div id="topnavList" class="hidden lg:text-base sm:block items-center w-auto mt-0 text-white p-0 z-20">
        <ul class="list-reset list-none font-semibold flex justify-end flex-wrap sm:flex-nowrap items-center px-0 pb-0">
          <li class="p-1 sm:p-0"><a class="topnav-link" href="../learn/">Learn</a></li>
          <li class="p-1 sm:p-0"><a class="topnav-link" href="../samples/">Samples</a></li>
          <li class="p-1 sm:p-0"><a class="topnav-link" href="../intro/">Intro</a></li>
          <li class="p-1 sm:p-0"><a class="topnav-link" href="../api/">API</a></li>
          <li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/products/register.html">Register</a></li>
          <li class="p-1 sm:p-0"><a class="topnav-link" href="../download.html">Download</a></li>
          <li class="p-1 sm:p-0"><a class="topnav-link" href="https://forum.nwoods.com/c/gojs/11">Forum</a></li>
          <li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/contact.html"
           target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/contact.html', 'contact');">Contact</a></li>
          <li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/sales/index.html"
           target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/sales/index.html', 'buy');">Buy</a></li>
        </ul>
      </div>
    </div>
    <hr class="border-b border-gray-600 opacity-50 my-0 py-0" />
  </nav>
    
    <div class="md:flex flex-col md:flex-row md:min-h-screen w-full max-w-screen-xl mx-auto">
      
    <div id="navSide" class="flex flex-col w-full md:w-40 lg:w-48 text-gray-700 bg-white flex-shrink-0">
      <div class="flex-shrink-0 px-8 py-4">
        <button id="navButton" class="rounded-lg md:hidden focus:outline-none focus:ring" aria-label="Navigation">
          <svg fill="currentColor" viewBox="0 0 20 20" class="w-6 h-6">
            <path id="navOpen" fill-rule="evenodd" d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 10a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM9 15a1 1 0 011-1h6a1 1 0 110 2h-6a1 1 0 01-1-1z" clip-rule="evenodd"></path>
            <path id="navClosed" class="hidden" fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path>
          </svg>
        </button>
      </div>
      <nav id="navList" class="min-h-screen hidden md:block sidebar-nav flex-grow px-1 lg:px-4 pb-4 md:pb-0 md:overflow-y-auto break-words">
  <a href="index.html">Basics</a>
  <a href="buildingObjects.html">Building Parts</a>
  <a href="usingModels.html">Using Models</a>
  <a href="dataBinding.html">Data Binding</a>
  <a href="react.html">GoJS with React</a>
  <a href="angular.html">GoJS with Angular</a>
  <a href="textBlocks.html">TextBlocks</a>
  <a href="shapes.html">Shapes</a>
  <a href="pictures.html">Pictures</a>
  <a href="panels.html">Panels</a>
  <a href="tablePanels.html">Table Panels</a>
  <a href="brush.html">Brushes</a>
  <a href="sizing.html">Sizing Objects</a>
  <a href="itemArrays.html">Item Arrays</a>
  <a href="changedEvents.html">Changed Events</a>
  <a href="transactions.html">Transactions</a>
  <a href="viewport.html">Coordinates</a>
  <a href="initialView.html">Initial View</a>
  <a href="collections.html">Collections</a>
  <a href="links.html">Links</a>
  <a href="linkLabels.html">Link Labels</a>
  <a href="connectionPoints.html">Link Points</a>
  <a href="ports.html">Ports</a>
  <a href="nodes.html">Nodes</a>
  <a href="debugging.html">Debugging</a>
  <a href="layouts.html">Layouts</a>
  <a href="trees.html">Trees</a>
  <a href="subtrees.html">SubTrees</a>
  <a href="groups.html">Groups</a>
  <a href="subgraphs.html">SubGraphs</a>
  <a href="sizedGroups.html">Sized Groups</a>
  <a href="selection.html">Selection</a>
  <a href="highlighting.html">Highlighting</a>
  <a href="animation.html">Animation</a>
  <a href="toolTips.html">ToolTips</a>
  <a href="contextmenus.html">Context Menus</a>
  <a href="events.html">Diagram Events</a>
  <a href="tools.html">Tools</a>
  <a href="commands.html">Commands</a>
  <a href="permissions.html">Permissions</a>
  <a href="validation.html">Validation</a>
  <a href="HTMLInteraction.html">HTML Interaction</a>
  <a href="layers.html">Layers &amp; Z-ordering</a>
  <a href="palette.html">Palette</a>
  <a href="overview.html">Overview</a>
  <a href="resizing.html">Resizing Diagrams</a>
  <a href="replacingDeleting.html">Replacing and Deleting</a>
  <a href="buttons.html">Buttons</a>
  <a href="templateMaps.html">Template Maps</a>
  <a href="legends.html">Legends and Titles</a>
  <a href="extensions.html">Extensions</a>
  <a href="geometry.html">Geometry Strings</a>
  <a href="grids.html">Grid Patterns</a>
  <a href="graduatedPanels.html">Graduated Panels</a>
  <a href="makingImages.html">Diagram Images</a>
  <a href="makingSVG.html">Diagram SVG</a>
  <a href="printing.html">Printing</a>
  <a href="serverSideImages.html">Server-side Images</a>
  <a href="nodeScript.html">GoJS in Node.js</a>
  <a href="testing.html">Testing</a>
  <a href="storage.html">Storage</a>
  <a href="performance.html">Performance</a>
  <a href="source.html">Building from Source</a>
  <a href="platforms.html">Platforms</a>
  <a href="deployment.html">Deployment</a>
      </nav>
    </div>      
      <div class="pt-4 px-2 md:px-0 lg:px-4 pb-16 w-full overflow-hidden">

<h1>Sizing GraphObjects</h1>
<p>
The size of a <a>GraphObject</a> is determined by the values of the <a>GraphObject.desiredSize</a>,
<a>GraphObject.minSize</a>, <a>GraphObject.maxSize</a> and <a>GraphObject.stretch</a> properties.
The actual size of an object after its containing panel measures and arranges it is given by several
read-only properties: <a>GraphObject.naturalBounds</a>, <a>GraphObject.measuredBounds</a>, and <a>GraphObject.actualBounds</a>.
</p>
<p>
The <a>GraphObject.width</a> property is exactly the same as the <a>Size.width</a> component of the <a>GraphObject.desiredSize</a>.
Similarly, the <a>GraphObject.height</a> property corresponds to the desiredSize's height.
The default value of <a>GraphObject.desiredSize</a> is <code>(NaN, NaN)</code> -- meaning that the size must be computed.
One can set the width to a real number and leave the height to be <code>NaN</code>, or vice-versa.
</p>
<p>
Users can also change the size of an object within a Part via the <a>ResizingTool</a>: Introduction to the <a href="tools.html#ResizingTool">ResizingTool</a>.
</p>

<h3 id="DesiredSizeMinSizeAndMaxSize">DesiredSize, MinSize, and MaxSize</h3>
<p>
When the <a>GraphObject.desiredSize</a> property is set to real numbers it gets that as its natural size.
When the desiredSize property is not set but there is a <a>GraphObject.stretch</a> value,
it will get the size of the available space.
When desiredSize is not set and there is no stretch,
an object prefers being its natural size,
based on the type of object that it is and the other properties that it has.
</p>
<p>
But the effective width and effective height, whether given by desiredSize or computed,
are each constrained by the <a>GraphObject.maxSize</a> and by the <a>GraphObject.minSize</a>.
The minimum size takes precedence over the maximum size in case of conflict.
</p>
<p>
The size for a GraphObject in a Table <a>Panel</a> may also be constrained by the width
of the column and the height of the row that the object is in.
</p>

<pre class="lang-js" id="shapeSizes"><code>
  diagram.add(
    $(go.Part,
      $(go.Panel, "Table",
        { defaultAlignment: go.Spot.Left },
        $(go.RowColumnDefinition, { column: 0, width: 200 }),
        $(go.RowColumnDefinition, { column: 1, width: 15 }),
        $(go.Shape, "Rectangle",
          { row: 0, column: 0, fill: "green",
            width: 100, height: 20 }),
        $(go.TextBlock, { row: 0, column: 2,
                          text: "desiredSize: 100x20, no minSize, no maxSize" }),
        $(go.Shape, "Rectangle",
          { row: 1, column: 0, fill: "red",
            width: 100, height: 20,
            minSize: new go.Size(150, 10) }),
        $(go.TextBlock, { row: 1, column: 2,
                          text: "desired: 100x20, min: 150x10" }),
        $(go.Shape, "Rectangle",
          { row: 2, column: 0, fill: "yellow",
            width: 100, height: 20,
            maxSize: new go.Size(50, 300) }),
        $(go.TextBlock, { row: 2, column: 2,
                          text: "desired: 100x20, max: 50x300" }),
        $(go.Shape, "Rectangle",
          { row: 3, column: 0, fill: "red",
            width: 100, height: 20,
            minSize: new go.Size(150, 10), maxSize: new go.Size(50, 300) }),
        $(go.TextBlock, { row: 3, column: 2,
                          text: "desired: 100x20, min: 150x10, max: 50x300" })
      )
    ));
</code></pre>
<script>goCode("shapeSizes", 600, 120)</script>

<h3 id="MeasuredAndActualSizes">Measured and Actual Sizes</h3>
<p>
Every GraphObject also has a <a>GraphObject.measuredBounds</a>,
which describes how big the object seems to be, and a <a>GraphObject.actualBounds</a>,
which describes the position and size of an object.
These read-only properties take into account any non-zero <a>GraphObject.angle</a> or non-unitary <a>GraphObject.scale</a>.
These measurements are in the containing <a>Panel</a>'s coordinate system.
</p>
<pre class="lang-js" id="sizedShapes"><code>
  function getSizeString(s) {
    return s.width.toFixed(2) + "x" + s.height.toFixed(2);
  }
  var table =
    $(go.Part, "Table",
      $(go.Shape, { name: "A", row: 0, column: 1,
                    figure: "Club", fill: "green", background: "lightgray",
                    width: 40, height: 40,
                    }),  // default angle is zero; default scale is one
      $(go.Shape, { name: "B", row: 0, column: 2,
                    figure: "Club", fill: "green", background: "lightgray",
                    width: 40, height: 40,
                    angle: 30 }),
      $(go.Shape, { name: "C", row: 0, column: 3,
                    figure: "Club", fill: "green", background: "lightgray",
                    width: 40, height: 40,
                    scale: 1.5 }),
      $(go.Shape, { name: "D", row: 0, column: 4,
                    figure: "Club", fill: "green", background: "lightgray",
                    width: 40, height: 40,
                    angle: 30, scale: 1.5 }),
      $(go.TextBlock, { row: 1, column: 1, margin: 4 },
        new go.Binding("text", "naturalBounds", getSizeString).ofObject("A")),
      $(go.TextBlock, { row: 1, column: 2, margin: 4 },
        new go.Binding("text", "naturalBounds", getSizeString).ofObject("B")),
      $(go.TextBlock, { row: 1, column: 3, margin: 4 },
        new go.Binding("text", "naturalBounds", getSizeString).ofObject("C")),
      $(go.TextBlock, { row: 1, column: 4, margin: 4 },
        new go.Binding("text", "naturalBounds", getSizeString).ofObject("D")),
      $(go.TextBlock, { row: 2, column: 1, margin: 4 },
        new go.Binding("text", "measuredBounds", getSizeString).ofObject("A")),
      $(go.TextBlock, { row: 2, column: 2, margin: 4 },
        new go.Binding("text", "measuredBounds", getSizeString).ofObject("B")),
      $(go.TextBlock, { row: 2, column: 3, margin: 4 },
        new go.Binding("text", "measuredBounds", getSizeString).ofObject("C")),
      $(go.TextBlock, { row: 2, column: 4, margin: 4 },
        new go.Binding("text", "measuredBounds", getSizeString).ofObject("D")),
      $(go.TextBlock, { row: 3, column: 1, margin: 4 },
        new go.Binding("text", "actualBounds", getSizeString).ofObject("A")),
      $(go.TextBlock, { row: 3, column: 2, margin: 4 },
        new go.Binding("text", "actualBounds", getSizeString).ofObject("B")),
      $(go.TextBlock, { row: 3, column: 3, margin: 4 },
        new go.Binding("text", "actualBounds", getSizeString).ofObject("C")),
      $(go.TextBlock, { row: 3, column: 4, margin: 4 },
        new go.Binding("text", "actualBounds", getSizeString).ofObject("D")),
      $(go.TextBlock, "naturalBounds:", { row: 1, column: 0, alignment: go.Spot.Left }),
      $(go.TextBlock, "measuredBounds:", { row: 2, column: 0, alignment: go.Spot.Left }),
      $(go.TextBlock, "actualBounds:", { row: 3, column: 0, alignment: go.Spot.Left })
    );
  diagram.add(table);
  setTimeout(function() {
    table.data = {};  // cause bindings to be evaluated after Shapes are measured
  }, 500);
</code></pre>
<script>goCode("sizedShapes", 600, 180)</script>
<p>
Note that the size of the regular 40x40 shape is 41x41.
The additional size is due to the thickness of the pen (<a>Shape.strokeWidth</a>) used to outline the shape.
Rotating or increasing the scale causes the 40x40 shape to actually take up significantly more space.
</p>
<p>
To summarize: the <a>GraphObject.desiredSize</a> (a.k.a. <a>GraphObject.width</a> and <a>GraphObject.height</a>)
and the <a>GraphObject.naturalBounds</a> are in the object's local coordinate system.
The <a>GraphObject.minSize</a>, <a>GraphObject.maxSize</a>, <a>GraphObject.margin</a>, <a>GraphObject.measuredBounds</a>, and
<a>GraphObject.actualBounds</a> are all in the containing <a>Panel</a>'s coordinate system, or in document
coordinates if there is no such panel because it is a <a>Part</a>.
</p>

<h3 id="StretchingOfGraphObjects">Stretching of GraphObjects</h3>
<p>
When you specify a <a>GraphObject.stretch</a> value other than <a>GraphObject,None</a>,
the object will stretch or contract to fill the available space.
However, the <a>GraphObject.maxSize</a> and <a>GraphObject.minSize</a> properties still limit the size.
</p>
<p>
But setting the <a>GraphObject.desiredSize</a> (or equivalently, the <a>GraphObject.width</a> and/or <a>GraphObject.height</a>)
will cause any stretch value to be ignored.
</p>
<p>
In the following examples the left column is constrained to have a width of 200.
</p>
<pre class="lang-js" id="stretchSizes"><code>
  diagram.add(
    $(go.Part,
      $(go.Panel, "Table",
        { defaultAlignment: go.Spot.Left },
        $(go.RowColumnDefinition, { column: 0, width: 200 }),
        $(go.RowColumnDefinition, { column: 1, width: 15 }),
        $(go.Shape, "Rectangle",
          { row: 0, column: 0, fill: "green",
            stretch: go.GraphObject.Fill }),
        $(go.TextBlock, { row: 0, column: 2,
                          text: "stretch: Fill, no minSize, no maxSize" }),
        $(go.Shape, "Rectangle",
          { row: 1, column: 0, fill: "red",
            stretch: go.GraphObject.Fill,
            minSize: new go.Size(150, 10) }),
        $(go.TextBlock, { row: 1, column: 2,
                          text: "stretch: Fill, min: 150x10" }),
        $(go.Shape, "Rectangle",
          { row: 2, column: 0, fill: "yellow",
            stretch: go.GraphObject.Fill,
            maxSize: new go.Size(50, 300) }),
        $(go.TextBlock, { row: 2, column: 2,
                          text: "stretch: Fill, max: 50x300" }),
        $(go.Shape, "Rectangle",
          { row: 3, column: 0, fill: "red",
            stretch: go.GraphObject.Fill,
            minSize: new go.Size(150, 10), maxSize: new go.Size(50, 300) }),
        $(go.TextBlock, { row: 3, column: 2,
                          text: "stretch: Fill, min: 150x10, max: 50x300" }),
        $(go.Shape, "Rectangle",
          { row: 4, column: 0, fill: "red",
            width: 100, stretch: go.GraphObject.Fill }),
        $(go.TextBlock, { row: 4, column: 2,
                          text: "desired width & stretch: ignore stretch" })
      )
    ));
</code></pre>
<script>goCode("stretchSizes", 600, 120)</script>
<p>
To summarize, if <a>GraphObject.desiredSize</a> is set, any <a>GraphObject.stretch</a> is ignored.
If <a>GraphObject.maxSize</a> conflicts with that value, it takes precedence.
And if <a>GraphObject.minSize</a> conflicts with those values, it takes precedence.
The width values are constrained independently of the height values.
</p>

<h2 id="StretchAndAlignment">Stretch and Alignment</h2>
<p>
The size of a <a>GraphObject</a> in a <a>Panel</a> is determined by many factors.
The <a>GraphObject.stretch</a> property specifies whether the width and/or height should take up all
of the space given to it by the Panel.
When the width and/or height is not stretched to fill the given space,
the <a>GraphObject.alignment</a> property controls where the object is placed if it is smaller than available space.
One may also stretch the width while aligning vertically, just as one may also
stretch vertically while aligning along the X axis.
</p>
<p>
The alignment value for a GraphObject, if not given by the value of <a>GraphObject.alignment</a>, may be inherited.
If the object is in a Table Panel, the value may inherit from the RowColumnDefinitions of
the row and of the column that the object is in.
Finally the value may be inherited from the <a>Panel.defaultAlignment</a> property.
</p>
<p>
If you specify a fill stretch (horizontal or vertical or both) and an alignment, the alignment will be ignored.
Basically if an object is exactly the size that is available to it, there is only one position for it, so all alignments are the same.
</p>

<h3 id="AlignmentOfShapes">Alignment of Shapes</h3>

<pre class="lang-js" id="shapeAlignment"><code>
  diagram.add(
    $(go.Part,
      $(go.Panel, "Table",
        { defaultAlignment: go.Spot.Left },
        $(go.RowColumnDefinition, { column: 0, width: 200 }),
        $(go.RowColumnDefinition, { column: 1, width: 15 }),
        $(go.Shape, "Rectangle",
          { row: 0, column: 0, fill: "lightblue",
            width: 100, height: 20, alignment: go.Spot.Left }),
        $(go.TextBlock, { row: 0, column: 2, text: "alignment: Left" }),
        $(go.Shape, "Rectangle",
          { row: 1, column: 0, fill: "lightblue",
            width: 100, height: 20, alignment: go.Spot.Center }),
        $(go.TextBlock, { row: 1, column: 2, text: "alignment: Center" }),
        $(go.Shape, "Rectangle",
          { row: 2, column: 0, fill: "lightblue",
            width: 100, height: 20, alignment: go.Spot.Right }),
        $(go.TextBlock, { row: 2, column: 2, text: "alignment: Right" }),
        $(go.Shape, "Rectangle",
          { row: 3, column: 0, fill: "yellow",
            height: 20, stretch: go.GraphObject.Horizontal }),
        $(go.TextBlock, { row: 3, column: 2, text: "stretch: Horizontal" }),
        $(go.Shape, "Rectangle",
          { row: 4, column: 0, fill: "yellow",
            height: 20, stretch: go.GraphObject.Horizontal, alignment: go.Spot.Right }),
        $(go.TextBlock, { row: 4, column: 2,
                          text: "stretch: Horizontal, ignore alignment" })
      )
    ));
</code></pre>
<script>goCode("shapeAlignment", 600, 120)</script>

<p>
When the element is larger than the available space, the <a>GraphObject.alignment</a>
property still controls where the element is positioned.
However the element will be clipped to fit.
</p>
<p>
To make things clearer in the following examples we have made the shape stroke thicker
and added a margin to separate the shapes.
</p>
<pre class="lang-js" id="bigShapeAlignment"><code>
  diagram.add(
    $(go.Part,
      $(go.Panel, "Table",
        { defaultAlignment: go.Spot.Left },
        $(go.RowColumnDefinition, { column: 0, width: 200 }),
        $(go.RowColumnDefinition, { column: 1, width: 15 }),
        $(go.Shape, "Rectangle",
          { row: 0, column: 0, fill: "lightblue", strokeWidth: 2,
            width: 300, height: 20, margin: 2, alignment: go.Spot.Left }),
        $(go.TextBlock, { row: 0, column: 2, text: "big obj alignment: Left" }),
        $(go.Shape, "Rectangle",
          { row: 1, column: 0, fill: "lightblue", strokeWidth: 2,
            width: 300, height: 20, margin: 2, alignment: go.Spot.Center }),
        $(go.TextBlock, { row: 1, column: 2, text: "big obj alignment: Center" }),
        $(go.Shape, "Rectangle",
          { row: 2, column: 0, fill: "lightblue", strokeWidth: 2,
            width: 300, height: 20, margin: 2, alignment: go.Spot.Right }),
        $(go.TextBlock, { row: 2, column: 2, text: "big obj alignment: Right" })
      )
    ));
</code></pre>
<script>goCode("bigShapeAlignment", 600, 100)</script>

      </div>
    </div>
  
  <div class="bg-nwoods-primary">
    <section class="max-w-screen-lg text-white container mx-auto py-2 px-12">
      <p id="version" class="leading-none mb-2 my-4">GoJS</p>
    </section>
  </div><footer class="bg-nwoods-primary text-white">
  <div class="container max-w-screen-lg mx-auto  px-8">
    <div class="w-full py-6">

        <div class="max-w-screen-lg xl:max-w-screen-xl mx-auto px-4 sm:px-6 md:px-8">
          <ul class="text-sm font-medium pb-14 sm:pb-20 grid grid-cols-1 sm:grid-cols-3 gap-y-10">
            <li class="list-none row-span-2">
              <h2 class="text-base font-semibold tracking-wide">GoJS</h2>
              <ul class="list-none space-y-4 md:space-y-1 px-0">
                <li>
                  <a href="../samples/index.html">Samples</a>
                </li>
                <li>
                  <a href="../learn/index.html">Learn</a>
                </li>
                <li>
                  <a href="../intro/index.html">Intro</a>
                </li>
                <li>
                  <a href="../api/index.html">API</a>
                </li>
                <li>
                  <a href="../changelog.html">Changelog</a>
                </li>
                <li>
                  <a href="https://github.com/NorthwoodsSoftware/GoJS">GitHub</a>
                </li>
              </ul>
            </li>
            <li class="list-none row-span-2">
              <h2 class="text-base font-semibold tracking-wide">Support</h2>
              <ul class="list-none space-y-4 md:space-y-1 px-0">
                <li>
                  <a href="https://www.nwoods.com/contact.html"
                  target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/contact.html', 'contact');">Contact</a>
                </li>
                <li>
                  <a href="https://forum.nwoods.com/c/gojs">Forum</a>
                </li>
                <li>
                  <a href="https://www.nwoods.com/app/activate.aspx?sku=gojs">Activate</a>
                </li>
                <li>
                  <a href="https://www.nwoods.com/sales/index.html"
                  target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/sales/index.html', 'buy');">Buy</a>
                </li>
                <li>
                  <a href="https://www.youtube.com/channel/UC9We8EoX596-6XFjJDtZIDg">Videos</a>
                </li>
              </ul>
            </li>
            <li class="list-none row-span-2">
              <h2 class="text-base font-semibold tracking-wide">Company</h2>
              <ul class="list-none space-y-4 md:space-y-1 px-0">
                <li>
                  <a href="https://www.nwoods.com">Northwoods</a>
                </li>
                <li>
                  <a href="https://www.nwoods.com/about.html">About Us</a>
                </li>
                <li>
                  <a href="https://www.nwoods.com/contact.html">Contact Us</a>
                </li>
                <li>
                  <a href="https://twitter.com/northwoodsgo">Twitter</a>
                </li>

              </ul>
            </li>
          </ul>


      <p class="text-sm text-gray-100 md:mb-6">
        Copyright 1998-2021 <a class="text-white" href="https://www.nwoods.com">Northwoods Software</a>
      </p>
    </div>
  </div>
</footer>  </body>

<script async src="https://www.googletagmanager.com/gtag/js?id=UA-1506307-5"></script> 
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date()); gtag('config', 'UA-1506307-5');
  var getOutboundLink = function(url, label) {
    gtag('event', 'click', {
      'event_category': 'outbound',
      'event_label': label,
      'transport_type': 'beacon'
    });
  }

  // topnav
  var topButton = document.getElementById("topnavButton");
  var topnavList = document.getElementById("topnavList");
  topButton.addEventListener("click", function() {
    this.classList.toggle("active");
    topnavList.classList.toggle("hidden");
    document.getElementById("topnavOpen").classList.toggle("hidden");
    document.getElementById("topnavClosed").classList.toggle("hidden");
  });
</script>
  <script src="../assets/js/prism.js"></script>
  <script src="../release/go.js"></script>
<script src="../extensions/Figures.js"></script>  <script src="../assets/js/goDoc.js"></script>
  <script>
    document.addEventListener("DOMContentLoaded", function() {
      if (window.go) document.getElementById('version').textContent = "GoJS version " + go.version;
      if (window.goDoc) window.goDoc();
      var d = window.diagrams;
      for (var i = 0; i < d.length; i++) {
        var dargs = d[i];
        goCodeExecute(dargs[0], dargs[1], dargs[2], dargs[3], dargs[4]);
      }
      if (window.extra) window.extra();
    });
  </script>
</html>
